
// MARK: 接口开始
interface IParamSchema {
    type: "integer";
    format: string;
}
interface IParam {
    name: string;
    description: string;
    required: boolean;
    schema: IParamSchema;
}

interface IVarData {
    type: string;
    format?: string;
    items?: {
        type?: string;
        format?: string;
        $ref?: string;
    }
}

interface ITSVar {
    /** 变量名字; 非必要需要加 ? */
    name: string;
    /** 变量注释 */
    description: string;
    /** 变量类型 */
    type: string;
    typeTail?: string;
}

interface ClassData {
    key: string;
    name: string;
    nameTail: string;
    desc: string;
    varList: ITSVar[];
}

interface HttpData {
    tags: string;
    desc: string;
    name: string;
    varList: ITSVar[];
}

// MARK: 接口结束

import { classNameMap } from './class_name';

/** java api 解析器 */
class UtilJavaApiParser {

    public isArray(param: any): boolean {
        return false;
    }

    public isObject(param: any): boolean {
        return false;
    }

    /** JAVA 类型转成 TS 类型 */
    private javaType2TS(type: string) {
        switch (type) {
            case 'number':
            case 'double':
            case 'integer':
            case 'int64':
            case 'int32':
            case 'long':
                return 'number';
            case 'string':
            case 'date-time':
                return 'string';
            case 'boolean':
                return 'boolean';
            case 'array':
            case 'object':
                return type;

            default:
                break;
        }
        return '';
    }


    //#region 解析 schema

    /** 路径最后一层, 
     * @example
     ```ts
         '/user/UpdateData';
         //匹配结果
         'UpdateData'
     ```
     */
    private refReg = /[^\/]+$/;

    /** 获取 $ref 类名 */
    private getRefName(ref: string) {
        try {
            const ret = ref.match(this.refReg);
            let className = ret[0];
            className = className.replace(/\«/g, '<');
            className = className.replace(/\»/g, '>');
            return className;
        } catch (error) {

        }
        return '';
    }

    /** 解析schema 属性
     * @param data
     * @param hasTail 是否是泛型
     */
    private parseSchemaProps(data: any, hasTail?: boolean) {
        const list: ITSVar[] = [];
        for (const key in data) {
            const item = data[key];

            const varData: ITSVar = {} as any;
            varData.name = key;
            varData.description = item.description;
            //解析枚举类型
            if (item.enum && item.enum.length > 0) {
                varData.type = item.enum.map((e) => {
                    return "'" + e + "'";
                }).join('|');
            } else {
                const type = this.javaType2TS(item.type);
                switch (type) {
                    case '':
                    case 'object':

                        if (item.$ref) {
                            if (hasTail) {
                                varData.type = 'T';
                            } else {
                                varData.type = this.getRefName(item.$ref);
                            }
                        };
                        break;
                    case 'array':
                        if (item.items.$ref) {
                            varData.type = this.getRefName(item.items.$ref);
                        } else {
                            if (item.items.type) {
                                varData.type = this.javaType2TS(item.items.type);
                            }
                        }
                        break;
                    default:
                        varData.type = type;
                        break;
                }

            }
            list.push(varData);
        }
        return list;
    }


    /** 解析 schema
     * @param json
     * @param ignoreFunc 忽略类名方法
     * 
     * @example
     ```ts

    parseSchemas(json, (key) => {
        if (key === '响应结果') return true;
        if (key == 'R') return true;
        if (key == 'PageVo') return true;
        if (key.indexOf('«') > -1) return true;
        return false;
    });
     ```
     */
    public parseSchemas(json, ignoreFunc: { (name: string): boolean }) {
        const map: Record<string, ClassData> = {};
        try {
            for (const key in json.components.schemas) {
                if (key === '响应结果') continue;
                if (ignoreFunc && ignoreFunc(key)) {
                    continue;
                }
                const schemaData = json.components.schemas[key];

                let className = key;

                /**@deprecated 不需要生产泛型类 */
                let tail = '';
                const data: ClassData = {} as any;
                data.nameTail = tail;
                if (classNameMap[className]) {
                    data.name = classNameMap[className];
                    data.desc = className;
                } else {
                    data.name = className;
                    if (schemaData['description']) {
                        data.desc = schemaData['description'];
                    } else {
                        data.desc = className;
                    }
                }
                if (!map[data.name]) {
                    map[data.name] = data;
                    data.varList = this.parseSchemaProps(schemaData.properties, !!tail);
                }
            }
        } catch (error) {

        }
        return map;
    }
    //#endregion 解析 schema

    //#region

    //MARK: 请求的 param
    /** 解析请求的 parameters */
    private parsePathParams(params: any[], name: string) {
        var clazz: ClassData = {} as any;
        clazz.name = name + '_param';
        const list: ITSVar[] = [];
        clazz.varList = list;
        clazz.desc = name + '请求参数';
        params.forEach((item) => {
            const data: ITSVar = {} as any;
            data.name = item.name;
            data.description = item.description;
            if (item.schema.$ref) {
                console.log('param $ref', item.schema.$ref);
            }
            data.type = this.javaType2TS(item.schema.type);
            list.push(data);
        });
        return clazz;
    }



    //MARK: 请求的 body
    /** 解析请求body 数据 */
    private parsePathBody(body: any) {
        try {
            const schema = body.content['application/json'].schema;
            const varData: ITSVar = {} as any;
            varData.name = 'data';
            varData.description = '请求数据';
            if (schema.$ref) {
                varData.type = this.getRefName(schema.$ref);
            } else {
                const type = this.javaType2TS(schema.type);
                switch (type) {
                    case 'array':
                        varData.typeTail = '[]';
                        if (schema.items.$ref) {
                            varData.type = this.getRefName(schema.items.$ref);
                        } else {
                            varData.type = this.javaType2TS(schema.items.type);
                        }

                        break;
                    case 'object':
                        if (schema.$ref) {
                            varData.type = this.getRefName(schema.$ref);
                        } else {
                            varData.type = this.javaType2TS(schema.type);
                        }
                        break;

                    default:
                        varData.type = type;
                        break;
                }
            }
            return varData;

        } catch (error) {
            console.log('parse path body error', error);
        }
        return undefined;
    }

    /** 解析返回数据 */
    private parsePathRes(res: any) {
        const schema = res['200']['content']['*/*'].schema;
        const varData: ITSVar = {} as any;
        varData.name = 'res?';
        varData.description = '返回数据';
        if (schema.$ref) {
            varData.type = this.getRefName(schema.$ref);
        } else {
            const type = this.javaType2TS(schema.type);
            switch (type) {
                case 'array':
                    varData.typeTail = '[]';
                    if (schema.items.$ref) {
                        varData.type = this.getRefName(schema.items.$ref);
                    } else {
                        varData.type = this.javaType2TS(schema.items.type);
                    }

                    break;
                case 'object':
                    if (schema.$ref) {
                        varData.type = this.getRefName(schema.$ref);
                    } else {
                        varData.type = this.javaType2TS(schema.type);
                    }
                    break;

                default:
                    varData.type = type;
                    break;
            }
        }

        if (/List\<(.+)\>/.test(varData.type)) {
            varData.type = varData.type.replace('List<', 'Array<');
        } else if (/Map\<(.+)\>/.test(varData.type)) {
            varData.type = varData.type.replace('Map<', 'Record<');
        } else if (/\bRes\b/.test(varData.type)) {
            varData.type = 'Res<any>';
        } else {

        }
        return varData;
    }

    /** 解析接口数据
     * @param json 
     * @param removePrefixUrl 移除url 头的
     */
    public parsePaths(json, removePrefixUrl?: string) {
        const retList: any[] = [];
        for (const key in json.paths) {
            const pathData = json.paths[key];
            for (const k in pathData) {
                const httpJson = pathData[k];
                const httpData: HttpData = {} as any;
                if (httpJson.tags) {
                    httpData.tags = httpJson.tags.join(';');
                }
                httpData.desc = httpJson.summary || '';

                const url = removePrefixUrl ? key.replace(removePrefixUrl, '') : key;
                httpData.name = url.replace(/^\//, '');
                httpData.name = httpData.name.replace(/\//g, '_');
                httpData.name = httpData.name.replace(/\{.+\}/g, '');
                httpData.name = httpData.name.replace(/\_$/g, '');
                httpData.name += '_' + k;
                httpData.varList = [{ name: 'url', type: `'${url}'`, description: httpData.desc + ' URL' }];
                httpData.varList.push({ name: 'method', type: `'${k}'`, description: '请求方法' + k });

                if (httpJson.parameters) {
                    const paramData = this.parsePathParams(httpJson.parameters, httpData.name);
                    retList.push(paramData);
                    httpData.varList.push({ name: 'params', description: '请求参数', type: paramData.name });
                }
                if (httpJson.requestBody) {
                    httpData.varList.push(this.parsePathBody(httpJson.requestBody));
                }
                if (httpJson.responses) {
                    httpData.varList.push(this.parsePathRes(httpJson.responses));
                }

                retList.push(httpData);
            }
        }

        return retList;
    }
    //#endregion 解析 paths
}

export const utilJavaApiParser = new UtilJavaApiParser();